﻿using NUnit.Framework;
using PatternTests.Tools;
using System.Reactive.Subjects;
using System;
using System.Threading;
using Patterns.DataProcessing.Aggregation;

namespace PatternTests.Aggregation
{
    [TestFixture]
    public class Aggregator
    {
        #region SetUp
        [SetUp]
        public void SetUp(){}
        #endregion

        #region Tests
        [Test]
        public void AggregatorSimpleDataTest()
        {
            const string aggregatorInstanceId = "testSum";
             var testInstance = new Aggregator<int>();
            testInstance.Register<Sum>(aggregatorInstanceId, (v) => v);
            var aggregate = testInstance.Resolve<Sum>(aggregatorInstanceId);

            testInstance.Accumulate(0);
            Assert.AreEqual(0, aggregate.Terminate());

            testInstance.Accumulate(1);
            Assert.AreEqual(1, aggregate.Terminate());

            testInstance.Accumulate(3);
            Assert.AreEqual(4, aggregate.Terminate());

            testInstance.Accumulate(6);
            Assert.AreEqual(10, aggregate.Terminate());

            aggregate.Initialize();
            Assert.AreEqual(0, aggregate.Terminate());
        }

        [Test]
        public void MultipleAgregatsOnComplexDataTest()
        {
            const string sumAggregateInstanceId = "testSum";
            const string countAggregateInstanceId = "testCount";
            var testInstance = new Aggregator<MarketData>();
            testInstance.Register<Sum>(sumAggregateInstanceId, (v) => v.volume);
            testInstance.Register<Count>(countAggregateInstanceId, (v) => v);
            var sumAggregate = testInstance.Resolve<Sum>(sumAggregateInstanceId);
            var countAggregate = testInstance.Resolve<Count>(countAggregateInstanceId);

            Assert.AreEqual(0, sumAggregate.Terminate());
            Assert.AreEqual(0, countAggregate.Terminate());

            testInstance.Accumulate(CreateMarketData(500.3, 5677, "GOOGLE", false));
            Assert.AreEqual(5677, sumAggregate.Terminate());
            Assert.AreEqual(1, countAggregate.Terminate());

            testInstance.Accumulate(CreateMarketData(501.3, 4500, "GOOGLE", true));
            Assert.AreEqual(10177, sumAggregate.Terminate());
            Assert.AreEqual(2, countAggregate.Terminate());

            testInstance.Accumulate(CreateMarketData(499.9, 1322, "GOOGLE", false));
            Assert.AreEqual(11499, sumAggregate.Terminate());
            Assert.AreEqual(3, countAggregate.Terminate());

            testInstance.Accumulate(CreateMarketData(503.5, 701, "GOOGLE", true));
            Assert.AreEqual(12200, sumAggregate.Terminate());
            Assert.AreEqual(4, countAggregate.Terminate());
        }
        #endregion

        #region Helpers
        public MarketData CreateMarketData(double price, int volume, string stock, bool isBuy)
        {
            return new MarketData{price = price, volume = volume, stock = stock, isBuy = isBuy};
        }
        #endregion
    }

    public struct MarketData
    {
        public int volume;
        public double price;
        public string stock;
        public bool isBuy;
    }
}
